package se.webbzon.boltzmann.game.environment;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import se.webbzon.boltzmann.battle.environment.BattleEnvironment;
import se.webbzon.boltzmann.configuration.Graphics;
import se.webbzon.boltzmann.environment.PlayerEnvironment;
import se.webbzon.boltzmann.game.Game;
import se.webbzon.boltzmann.game.object.inventory.layout.AbstractGameInventoryLayout;
import se.webbzon.boltzmann.game.object.inventory.layout.GameInventoryLayoutHigh;
import se.webbzon.boltzmann.game.object.inventory.layout.GameInventoryLayoutLow;
import se.webbzon.boltzmann.game.object.inventory.layout.GameInventoryLayoutMedium;
import se.webbzon.boltzmann.game.region.RegionObject;
import se.webbzon.boltzmann.inflatorgroup.EnvironmentInflatorGroup;

public class GameEnvironment extends PlayerEnvironment {
	
	// The game associated with this game environment
	private final Game game;
	
	// The battle environment associated with this environment
	private final BattleEnvironment battleEnv;
	
	// The layout of the game inventory
	private final AbstractGameInventoryLayout inventoryLayout;
	
	// A set of all persistent instances
	private final Set<Long> regionPersistences, gamePersistences;

	/*============================================================
	Constructors
	============================================================*/
	
	public GameEnvironment(	Game game,
							BattleEnvironment battleEnv,
							EnvironmentInflatorGroup inflatorGroup) 
									throws Exception {
		super(inflatorGroup);
		this.game = game;
		this.battleEnv = battleEnv;
		switch (Graphics.instance().getResolution()) {
		case HIGH:
			inventoryLayout = new GameInventoryLayoutHigh();
			break;
		case MEDIUM:
			inventoryLayout = new GameInventoryLayoutMedium();
			break;
		default:
			inventoryLayout = new GameInventoryLayoutLow();
		}
		regionPersistences = new HashSet<Long>();
		gamePersistences = new HashSet<Long>();
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the game inventory layout associated with this game environment. **/
	public AbstractGameInventoryLayout getInventoryLayout() {
		return inventoryLayout;
	}
	
	/** Returns the game associated with this game environment. **/
	public Game getGame() {
		return game;
	}
	
	/** Returns the backup of the game associated with this game environment. 
	 * If the requested backup is zero then the original game is returned. **/
	public Game getBackup(int backup) {
		Game game = this.game;
		for (int i = 0; i < backup; i++) {
			if (game.hasBackup())
				game = game.getBackup();
		}
		return game;
	}
	
	/** Returns the battle environment associated with this game environment. **/
	public BattleEnvironment getBattleEnvironment() {
		return battleEnv;
	}
	
	/** Adds a region persistence by storing the id of the 
	 * provided region object. **/
	public boolean addRegionPersistence(RegionObject instance) {
		return regionPersistences.add(instance.getId());
	}
	
	/** Removes a region persistence by removing the id of the 
	 * provided region object from the environment. **/
	public boolean removeRegionPersistence(RegionObject instance) {
		return regionPersistences.remove(instance.getId());
	}
	
	/** Returns true if the provided region object has
	 * been stored as a region persistent object. **/
	public boolean hasRegionPersistence(RegionObject instance) {
		return regionPersistences.contains(instance.getId());
	}
	
	/** Clears all the region persistences. **/
	public void clearRegionPersistences() {
		regionPersistences.clear();
	}
	
	/** Adds a game persistence by storing the id of the 
	 * provided region object. **/
	public boolean addGamePersistence(RegionObject instance) {
		long id = instance.getId();
		if (id == 0)
			return false;
		else
			return gamePersistences.add(id);
	}
	
	/** Removes a game persistence by removing the id of the 
	 * provided region object from the environment. **/
	public boolean removeGamePersistence(RegionObject instance) {
		long id = instance.getId();
		if (id == 0)
			return false;
		else
			return gamePersistences.remove(id);
	}
	
	/** Returns true if the provided region object has
	 * been stored as a game persistent object. **/
	public boolean hasGamePersistence(RegionObject instance) {
		long id = instance.getId();
		if (id == 0)
			return false;
		else
			return gamePersistences.contains(id);
	}
	
	/** Clears all the game persistences. **/
	public void clearGamePersistences() {
		gamePersistences.clear();
	}
	
	/** Returns a list of all the game persistences. **/
	public Collection<RegionObject> getGamePersistances() {
		ArrayList<RegionObject> persistences = new ArrayList<RegionObject>();
		for (Long id : gamePersistences)
			persistences.add(new RegionObjectImpl(id));
		return persistences;
	}

}
